#!/usr/bin/python
# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
from ExerciseRecord import ExerciseRecord
from ExerciseRecord import RawDataRecord
from ExerciseRecord import UserInfo
import sqlite3 as sqlite
import threading, Queue
import time
from datetime import datetime
import GmailManager
import os
import pexpect
from CommandThread import Command
import urllib2
#change
#note:
time_record = []
#note:
_exercise_record = {}

'''_group_record[count, first_time, last_time, tid0, tid1, tid2, tid3, tid4] 
count: numbers of detecting cheat
first_time: the moment when cheat group detected at first time
last_time: the moment when cheat group detected at last time
tid0-4: tagid of users' that may be cheat'''
_group_record = {}

#system parameters
_const = {}
_userinfo = {}
#note:
class SQL_Thread(threading.Thread):
    #_data = []
    _IsIdle = True
    _delay = 0
    
    def get_const(self, key):
        return _const[key]
    
    def del_db(self):
        '''
        print "sql init, rm tagdata.db"
        pexpect.run('sudo rm /home/pi/tagdata.db')
        time.sleep(2)

        print "rm done"
        '''
        client_con = self.client_sql_connect(None)
        with client_con:
            cur = client_con.cursor() 
            cur.execute("DELETE FROM Suspect_List")
            cur.execute("DELETE FROM SportData")
            cur.execute("DELETE FROM Accumulate")
            print "clear tagdata.db"
        
    def init(self):
        
        #if RPI is client, it needs to create a temporary DB.
        if _const["rpi_mode"] == 2:            
            
            client_con = self.client_sql_connect(None)
            
            with client_con:
                client_cur = client_con.cursor()
                client_cur.execute('CREATE TABLE IF NOT EXISTS "Accumulate" ("SID"  PRIMARY KEY ,"ThisSemesterRun" INTEGER,"ThisSemesterWalk" INTEGER,"total_run" INTEGER,"total_walk" INTEGER,"LastExerciseWeekInYear" INTEGER,"ThisSemesterTotalWeeks" INTEGER,"TotalWeeks" INTEGER)')
                client_cur.execute('CREATE TABLE IF NOT EXISTS "SportData" ("SID" VARCHAR,"runtime" VARCHAR,"RunDistance" INTEGER,"RunDuration" INTEGER,"WalkDistance" INTEGER,"WalkDuration" INTEGER,"Kcal" FLOAT,"speed" FLOAT,"CID" VARCHAR,"FID" VARCHAR,"WeekInYear" INTEGER, PRIMARY KEY ("SID","runtime") )')
                client_cur.execute('CREATE TABLE IF NOT EXISTS Suspect_List(Suspect_date,tagid1,tagid2,tagid3,tagid4,tagid5,PRIMARY KEY(Suspect_date,tagid1,tagid2))')
            return
        
        #if RPI is server or combo, then load user information from DB.
        con = self.sql_connect()
        with con:
            cur = con.cursor()
            cur.execute(
                        "SELECT UserData.SID, \
                        UserData.name, \
                        UserData.weight, \
                        UserData.email, \
                        UserData.TagID, \
                        Accumulate.ThisSemesterRUN, \
                        Accumulate.ThisSemesterWALK, \
                        Accumulate.total_run, \
                        Accumulate.total_walk, \
                        Accumulate.LastExerciseWeekInYear, \
                        Accumulate.ThisSemesterTotalWeeks, \
                        Accumulate.TotalWeeks \
                        FROM TagData, UserData LEFT OUTER JOIN Accumulate ON UserData.SID = Accumulate.SID \
                        WHERE TagData.TagID = UserData.TagID")
            tagdata = cur.fetchone()
            while tagdata != None:
                _userinfo[tagdata[UserInfo.TAGID]] = UserInfo(tagdata[UserInfo.SID], 
                                                           tagdata[UserInfo.NAME], 
                                                           tagdata[UserInfo.WEIGHT], 
                                                           tagdata[UserInfo.EMAIL], 
                                                           tagdata[UserInfo.CUR_RUN], 
                                                           tagdata[UserInfo.CUR_WALK], 
                                                           tagdata[UserInfo.TOTAL_RUN], 
                                                           tagdata[UserInfo.TOTAL_WALK], 
                                                           tagdata[UserInfo.LAST_WEEK], 
                                                           tagdata[UserInfo.CUR_WEEK], 
                                                           tagdata[UserInfo.TOTAL_WEEK])
                #print tagdata[UserInfo.TAGID]
                tagdata = cur.fetchone()
            #print _userinfo.viewvalues()
            
    def sql_connect(self):
        return sqlite.connect("/usr/share/nginx/www/ehealth.db") 
            
        
    def client_sql_connect(self, filename):
        if filename == None:
            filename = 'tagdata.db'
        return sqlite.connect("/home/pi/" + filename)
    
    
    def insert_userinfo(self, userlist):
        con = self.sql_connect()
        with con:
            cur = con.cursor()
            sqlcmd = '''INSERT INTO UserData(SID, 
                        CID, 
                        name, 
                        gender, 
                        department, 
                        height, 
                        weight, 
                        email, 
                        TagID) VALUES('%s', '%s', '%s', '%s', '%s', '%f', '%f', '%s', '%s')'''
            
            sqlcmd2 = '''INSERT INTO TagData(TagID, 
                         status, 
                         SID, 
                         date) VAlUES('%s', '%s', '%s', '%s')'''
            for userinfo in userlist:
                try:
                    print sqlcmd %(userinfo[0], userinfo[1], userinfo[2], userinfo[3], userinfo[4], float(userinfo[5]), float(userinfo[6]), userinfo[7], userinfo[8])
                    cur.execute(sqlcmd %(userinfo[0], userinfo[1], userinfo[2], userinfo[3], userinfo[4], float(userinfo[5]), float(userinfo[6]), userinfo[7], userinfo[8]))
                    print sqlcmd2 %(userinfo[8], 'a', userinfo[0], time.strftime('%Y-%m-%d %X', time.localtime(time.time())))
                    cur.execute(sqlcmd2 %(userinfo[8], 'a', userinfo[0], time.strftime('%Y-%m-%d %X', time.localtime(time.time()))))
                except:
                    print 'insert user fail %s' %userlist
             
    #read scheduler from DB and create timer to alarm clients. 
    def read_timer(self):
        command = []
        con = self.sql_connect()
        with con:
            cur = con.cursor()
            sqlcmd = "SELECT * FROM system_time WHERE wek = '%s'"
            dt = datetime.now().strftime('%a')
            print sqlcmd %(dt)
            cur.execute(sqlcmd %(dt))
            timer = cur.fetchone()
            
            while timer != None:
                print timer
                command.append(Command('timer', _const['client_IP'][timer[2][0]], int(timer[3]), int(timer[4])))
                timer = cur.fetchone()
        
        return command
    
    #send email with error messages to specific administrator.
    def send_error_mail(self, title, content):
        mail = _const("mailuser")
        print('sent error mail to %s' % mail)
        GmailManager.sendGmailSmtp(mail, _const("mailpassword"), mail, title, content)   
    
    #send email with exercise record to user     
    def send_email(self, run_distance, run_duration, walk_distance, walk_duration, kcal, start_time, user, avgspeed):
        v0 = str("%.2f"%(run_distance / 1000.00)).encode('utf-8')
        v1 = str("%.2f"%(run_distance / _const['run_lap'])).encode('utf-8')
        v2 = str("%.2f"% (run_duration / 60.00)).encode('utf-8')
        v3 = str("%.2f"% (walk_distance / 1000.00)).encode('utf-8')
        v4 = str("%.2f"% (walk_distance / _const['run_lap'])).encode('utf-8')
        v5 = str("%.2f"% (walk_duration / 60.00)).encode('utf-8')
        v6 = str("%.2f"%kcal).encode('utf-8')
        v7 = str("%.2f"%avgspeed).encode('utf-8')
        v8 = str("%.2f"% (user.cur_run / 1000.00)).encode('utf-8')
        v9 = str("%.2f"% (user.cur_run / _const['run_lap'])).encode('utf-8')
        v10 = str("%.2f"% (user.cur_walk / 1000.00)).encode('utf-8')
        v11 = str("%.2f"% (user.cur_walk / _const['run_lap'])).encode('utf-8')
        v12 = str(user.cur_week).encode('utf-8')
        #print "%x" % v12
        #content = u"Hi, " +user.name+u" :\r\n�z��"+time.strftime('%Y-%m-%d %X', time.localtime(record.start_time))+u"�]�F"+v0+u"�����]"+v1+u"��^�A��O"+v2+u"�����A���F"+v3+u"�����]"+v4+u"��^�A��O"+v5+u"�����A�@��Ӽ��q"+v6+u"kcal�A�����ɳt��"+v7+u"kmh�C�[�o�I\r\nehealth�t�ηq�W\r\nP.S��ĳ�O�d�̫�@��e-mail�@���B�ʬ����ҩ�C\r\n.\r\n"
        content = "\tHi, %s:\r\n\
        \t�z��%s �]�F%s�����]%s��^�A��O%s�����A���F%s�����]%s��^�A��O%s�����A�@��Ӽ��q%skcal�A�����ɳt��%skm/h�C\r\n\
        \t���Ǵ��֭p�]�F%s�����]%s��^�A���F%s�����]%s��^�A�B��%s�g�C\r\n\
        \t�[�o�I\r\n\
        ehealth�t�ηq�W\r\n\
        P.S��ĳ�O�d�̫�@��e-mail�@���B�ʬ����ҩ�C\r\n" %(user.name.encode('utf-8'),
                                           start_time.encode('utf-8'),
                                           v0,v1,v2,
                                           v3,v4,v5,
                                           v6,v7,
                                           v8,v9,v10,v11,v12)
        
        print GmailManager.sendGmailSmtp(_const["mailuser"], _const["mailpassword"], user.email, '�B�ʬ���', content) #gmail
        #return content


    def insertSportData(self, cur, weeknumber, record, user):
        sqlcmd = "INSERT INTO SportData(SID, runtime, RunDistance, RunDuration, WalkDistance, WalkDuration, Kcal, Speed, CID, FID, WeekInYear) VALUES('%s', '%s', %d, %d, %d, %d, %.2f, %.2f, '%s', '%s', %d)"
        avgspeed = float(record.run_distance + record.walk_distance) / (record.run_duration + record.walk_duration)
        avgspeed = avgspeed * 3.6
        cur.execute(sqlcmd % (user.sid, time.strftime('%Y-%m-%d %X', time.localtime(record.start_time)), record.run_distance, record.run_duration, record.walk_distance, record.walk_duration, record.kcal, avgspeed, _const["campusid"], _const["fieldid"], weeknumber))
        if _const["rpi_mode"] == 3:
            self.send_email(record.run_distance, record.run_duration, record.walk_distance, record.walk_duration, avgspeed, record.kcal, record.start_time, usr, avgspeed)

    def isIdle(self):
        return self._IsIdle
    
    #only work in server. It updates records to DB.
    def updateDB(self, filename):
        if _const["rpi_mode"] == 1:
            con = self.sql_connect()
            with con:
                cur = con.cursor()
                client_con = self.client_sql_connect(filename)
                with client_con:
                    client_cur = client_con.cursor()
                    
                    #copy suspect_list from client DB to suspect_list of server DB
                    client_cur.execute("SELECT * FROM Suspect_List")
                    row = client_cur.fetchone()
                    while row != None:
                        sqlcmd = "INSERT INTO Suspect_List(Suspect_date, tagid1, tagid2, tagid3, tagid4, tagid5) VALUES('%s', '%s', '%s', '%s', '%s', '%s')"
                        #print sqlcmd %(row[0], row[1], row[2], row[3], row[4], row[5])
                        try:
                            cur.execute(sqlcmd %(row[0], row[1], row[2], row[3], row[4], row[5]))
                        except:
                            send_error_mail('insert suspectlist error', sqlcmd)
                        row = client_cur.fetchone()
                    
                    client_cur.execute("SELECT * FROM SportData")    
                    row = client_cur.fetchone()
                    while row != None:
                        sqlcmd = '''INSERT INTO SportData(SID, 
                        runtime, 
                        RunDistance, 
                        RunDuration, 
                        WalkDistance, 
                        WalkDuration, 
                        Kcal, 
                        Speed, 
                        CID, 
                        FID, 
                        WeekInYear) VALUES('%s', '%s', %d, %d, %d, %d, %.2f, %.2f, '%s', '%s', %d)'''
                        tid = row[0]
                        while len(tid) < 16:
                            tid = '0' + tid
                        user = _userinfo[tid]
                        sid = user.sid
                        kcal = row[6] * user.weight
                        #print sqlcmd %(sid, row[1], row[2], row[3], row[4], row[5], kcal, row[7], row[8], row[9], row[10])
                        try:
                            cur.execute(sqlcmd %(sid, row[1], row[2], row[3], row[4], row[5], kcal, row[7], row[8], row[9], row[10]))
                        except:
                            send_error_mail('insert sportdata error', sqlcmd)
                        self.send_email(row[2], row[3], row[4], row[5], row[6], row[1], user, row[7])

                        row = client_cur.fetchone()
                        
                    client_cur.execute("SELECT * FROM Accumulate")    
                    row = client_cur.fetchone()
                    while row != None:                        
                        tid = row[0]
                        while len(tid) < 16:
                            tid = '0' + tid
                        try:
                            user = _userinfo[tid]
                        except:
                            self.init()
                            try:
                                user = _userinfo[tid]
                            except:
                                send_error_mail('user file does not exist error', tid)
                            continue
                            
                        if user.total_run == None:
                            sqlcmd = "INSERT INTO Accumulate(SID, \
                            ThisSemesterRun, \
                            ThisSemesterWalk, \
                            total_run, \
                            total_walk, \
                            LastExerciseWeekInYear, \
                            ThisSemesterTotalWeeks, \
                            TotalWeeks) VALUES('%s', %d, %d, %d, %d, %d, %d, %d)"   
                            
                            user.cur_run = row[1]
                            user.cur_walk = row[2]
                            user.total_run = row[3]
                            user.total_walk = row[4]
                            user.cur_week = row[6]
                            user.total_week = row[7]
                            user.last_week = row[5]         
                            
                            cur.execute(sqlcmd % (user.sid,
                                                 user.cur_run,
                                                 user.cur_walk,
                                                 user.total_run,
                                                 user.total_walk,
                                                 user.last_week,
                                                 user.cur_week,
                                                 user.total_week))
                            
                        else:
                            sqlcmd = "UPDATE Accumulate SET ThisSemesterRun=%d, \
                            ThisSemesterWalk=%d, \
                            total_run=%d, \
                            total_walk=%d, \
                            LastExerciseWeekInYear=%d, \
                            ThisSemesterTotalWeeks=%d, \
                            TotalWeeks=%d \
                            WHERE SID='%s'"
                            
                            user.cur_run += row[1]
                            user.cur_walk += row[2]
                            user.total_run += row[3]
                            user.total_walk += row[4]
                            if user.last_week != row[5]:
                                user.cur_week += 1
                                user.total_week += 1
                            user.last_week = row[5]
                            
                            cur.execute(sqlcmd % (user.cur_run,
                                                 user.cur_walk,
                                                 user.total_run,
                                                 user.total_walk,
                                                 user.last_week,
                                                 user.cur_week,
                                                 user.total_week,
                                                 user.sid))
                        row = client_cur.fetchone()
   
    def scpDB(self):
        print 'scp tagdb starting'
        filename = _const['current_IP'] + '_' + str(_const['exercise_mode']) +'_tagdata.db'
        ssh = pexpect.spawn('sudo scp /home/pi/tagdata.db pi@' + _const['server_IP'] + ':/home/pi/' + filename)
        
        #Expected respond from server are 'password'(0), EOF(1) and TIMEOUT(2).
        index = ssh.expect(['password:', pexpect.EOF, pexpect.TIMEOUT])
        
        #if 'scp' command works well, we will receive respond('password') to ask to enter password.
        #if not, it means something go wrong. we will try again later.
        if index == 0:
            ssh.sendline('raspberry')
            respone = ssh.expect(['100%'])
            while respone != 0:
                time.sleep(1)                        
                respone = ssh.expect(['100%'])
                time.sleep(1)
            try:
                f = urllib2.urlopen("http://" + _const['server_IP'] + ":8011/?update=" + filename)
                if f.read() == 'update cmd received':     
                    self._IsIdle = True                       
                    self.del_db()
            except:
                pass
        else:
            time.sleep(self._delay)
            self._delay += 1
            if self._delay > 255:
                self._IsIdle = True   
                self._delay = 0
    
    def run(self):
        
        while True:
            _data = []
            
            #only work in client or combo
            #if there is nothing in time_record, it means no records need to be dealt with.
            if len(time_record) == 0:
                
                #clear the suspect list in group_record.
                _group_record.clear()
                time.sleep(5)
                
                if self._IsIdle == False:
                    if _const["rpi_mode"] == 2:
                        self.scpDB()
                    else:
                        self._IsIdle = True
                continue
            else:
                self._IsIdle = False
            
            #get the first record to deal with   
            tagid = time_record[0]
            
            #if the record is suspect_list, insert record into DB.
            if tagid in _group_record.keys():
                
                con = self.client_sql_connect(None) if _const["rpi_mode"] == 2 else self.sql_connect()
                time_record.pop(0)
                with con:
                    cur = con.cursor()
                    sqlcmd = "INSERT INTO Suspect_List(Suspect_date, tagid1, tagid2, tagid3, tagid4, tagid5) VALUES('%s', '%s', '%s', '%s', '%s', '%s')"
                    gRecord = _group_record[tagid]
                    gList = ["", "", "", "", ""]
                    for i in range(3, len(gRecord)):
                        gList[i - 3] = str(gRecord[i])
                    print sqlcmd %(time.strftime('%Y-%m-%d %X', time.localtime(gRecord[1])),
                                         gList[0], 
                                         gList[1], 
                                         gList[2], 
                                         gList[3], 
                                         gList[4])
                    cur.execute(sqlcmd %(time.strftime('%Y-%m-%d %X', time.localtime(gRecord[1])),
                                         gList[0], 
                                         gList[1], 
                                         gList[2], 
                                         gList[3], 
                                         gList[4]))
                    del _group_record[tagid]
                    #print "insert suspect"
                continue
            
            #if the record is exercise_record, insert or update record into DB.
            period = time.time() - _exercise_record[tagid].last_time     
            
            #time.sleep(1)
            if period >= _const["flush_time"]:
                if _exercise_record[tagid].run_duration != 0 or _exercise_record[tagid].walk_duration != 0:
                    
                    _data.append(time_record.pop(0))
                else:
                    del time_record[0]
                    del _exercise_record[tagid]
            
            con = self.client_sql_connect(None) if _const["rpi_mode"] == 2 else self.sql_connect()
            with con:
                cur = con.cursor()
                weeknumber = int(time.strftime("%Y%W", time.localtime()))
                
                for tid in _data:
                    #if _const["debug"]:
                    #    print "%s in sql thread " %tid
                    record = _exercise_record[tid]
                    user = None
                    sqlcmd =""
                    
                    try:
                        user = _userinfo[tid]
                    except:
                        _userinfo[tid] = UserInfo(tid, 
                                                   "", 
                                                   1, 
                                                   "", 
                                                   0, 
                                                   0, 
                                                   0, 
                                                   0, 
                                                   0, 
                                                   0, 
                                                   0)
                        user = _userinfo[tid]
                    
                    if user.total_run == 0:
                        sqlcmd = "INSERT INTO Accumulate(SID, \
                        ThisSemesterRun, \
                        ThisSemesterWalk, \
                        total_run, \
                        total_walk, \
                        LastExerciseWeekInYear, \
                        ThisSemesterTotalWeeks, \
                        TotalWeeks) VALUES('%s', %d, %d, %d, %d, %d, %d, %d)"   
                        
                        user.cur_run = record.run_distance
                        user.cur_walk = record.walk_distance
                        user.total_run = record.run_distance
                        user.total_walk = record.walk_distance
                        user.cur_week = 1
                        user.total_week = 1
                        user.last_week = weeknumber         
                        
                        print sqlcmd % (user.sid,
                                         record.run_distance,
                                         record.walk_distance,
                                         record.run_distance,
                                         record.walk_distance,
                                         weeknumber, 1, 1)
                        cur.execute(sqlcmd % (user.sid,
                                             record.run_distance,
                                             record.walk_distance,
                                             record.run_distance,
                                             record.walk_distance,
                                             weeknumber, 1, 1))
                        
                    else:
                        sqlcmd = "UPDATE Accumulate SET ThisSemesterRun=%d, \
                        ThisSemesterWalk=%d, \
                        total_run=%d, \
                        total_walk=%d, \
                        LastExerciseWeekInYear=%d, \
                        ThisSemesterTotalWeeks=%d, \
                        TotalWeeks=%d \
                        WHERE SID='%s'"
                        
                        user.cur_run += record.run_distance
                        user.cur_walk += record.walk_distance
                        user.total_run += record.run_distance
                        user.total_walk += record.walk_distance
                        if user.last_week != weeknumber:
                            user.cur_week += 1
                            user.total_week += 1
                        user.last_week = weeknumber
                        
                        print sqlcmd % (user.cur_run,
                                             user.cur_walk,
                                             user.total_run,
                                             user.total_walk,
                                             user.last_week,
                                             user.cur_week,
                                             user.total_week,
                                             user.sid)
                        cur.execute(sqlcmd % (user.cur_run,
                                             user.cur_walk,
                                             user.total_run,
                                             user.total_walk,
                                             user.last_week,
                                             user.cur_week,
                                             user.total_week,
                                             user.sid))
                        
                        #endif
                        
                    
                    self.insertSportData(cur, weeknumber, record, user)
                    #print _exercise_record.keys()
                    del _exercise_record[tid]
                    #print _exercise_record.keys()
                        
class Exercise_Thread(threading.Thread):
    '''
    classdocs
    '''
    #note:
    #_const = {}
    # contain all exercise record
    #_exercise_record = {}
    
    #reader
    # contain unhandled data(tagid, time ,point) received from reader. {"point":RawDataRecord}
    _rawdata_record = {"a1" : [], "a2" : [], "b1" : [], "b2" : [], "c1" : [], "c2" : [], "d1" : [], "d2" : []}
    #note:
    _portname = []
    #note:
    _debug = False
    
    def init(self, records):
        for item in records:
            self._exercise_record.append(item)
    #note:
    def addExerciseRecord(self, item, point):
        #note:
        newRecord = _exercise_record[item.tag_id] if (item.tag_id in _exercise_record.keys()) else ExerciseRecord()

        dis = 0
        try:
            dis = _const[newRecord.last_point + point] if (newRecord.last_point != "") else 0
        except:
            print 'fail to get distance from configure.xml'
            
        if(True):
            t = item.current_time - newRecord.last_time
            speed = dis * 60 / t
            #note
            if(speed <= _const['fast_speed'] and speed > _const['walk_speed']):
                vo2 = 0.0
                cal = 0.0
                #user = None
                wt = 1
                
                if _const["rpi_mode"] == 3:
                    try:
                        user = _userinfo[item.tag_id]
                        wt = user.weight
                    except:                    
                        wt = 1
                    
                if(speed > _const['run_speed']):
                    newRecord.run_distance += dis
                    newRecord.run_duration += t
                    vo2 = 3.5 + (0.2 * speed)
                else:
                    newRecord.walk_distance += dis
                    newRecord.walk_duration += t
                    vo2 = 3.5 + (0.1 * speed)
                 
                cal = (vo2 * wt / 200) * t / 60.0
                newRecord.kcal += cal
                

        newRecord.last_point = point
        newRecord.last_time = item.current_time
        #note:
        if(newRecord.tag_id == ""):
            newRecord.tag_id = item.tag_id
            newRecord.start_time = item.current_time
            _exercise_record[item.tag_id] = newRecord    
            '''       
            if(self._debug):
                print "create new exercise record "
                '''
        else:
            try:
                time_record.remove(item.tag_id)  #note:
            except:
                pass
            '''
            if(self._debug):
                print "tag id %s repeated, move to last " % (item.tag_id)
                '''
        
        time_record.append(item.tag_id)  #note:       
        '''
        if(self._debug):
            print r
            print "all records %s" % _exercise_record.keys()
            print "time sequence %s" % time_record
              '''
        return r
    
    def searchGroup(self, point):
        if len(self._rawdata_record[point]) == 0:
            time.sleep(1)
            #print "sleep 1 seconds"
            return
        new_group = {}
        keyValue = 0L
        count = 0       
        
        item = self._rawdata_record[point].pop(0)  #note:
        cheatInterval = item.current_time + 10
        # create new record and group
        while (len(self._rawdata_record[point]) >= 0):
                     
            if count < 5:
                if item.current_time <= cheatInterval:
                    new_group[item.tag_id] = item
                    if count != len(new_group):
                        new_record = self.addExerciseRecord(item, point)  #
            
                        if new_record == None:
                            continue
                    count = len(new_group)
                else:
                    self.addExerciseRecord(item, point)
                    break                                        
            else:
                break
            
            if (len(self._rawdata_record[point]) > 0):
                item = self._rawdata_record[point].pop(0) 
            else:
                break
        if count > 1:
            
            new_group.keys().sort()
            for i in new_group.keys():
                keyValue = keyValue * 1000 + i % 1000
            if keyValue in _group_record.keys():
                
                cheatTime = _group_record[keyValue][1]
                if time.time() - cheatTime > _const["flush_time"]:
                    
                    if _group_record[keyValue][0] >= 4:
                        time_record.insert(0, keyValue)
                    else:
                        _group_record[keyValue][0] = 0
                        _group_record[keyValue][1] = item.current_time

                _group_record[keyValue][0] += 1
                _group_record[keyValue][2] = item.current_time
            else:
                _group_record[keyValue] = [0, item.current_time, item.current_time] + new_group.keys()
                
                #_group_record[keyValue] = new_group.keys()
            if self._debug:
                print "suspectlist update: %s" %_group_record[keyValue]
    
        
    def run(self):
        while True:
        
            # search group
            for portname in self._portname:
                self.searchGroup(portname)

        
        
